Add streaming output via editMessageText + /verbose tool display#21
Add streaming output via editMessageText + /verbose tool display#211872-svg wants to merge 1 commit intomoazbuilds:masterfrom
Conversation
262862d to
b60ba09
Compare
- Stream-json output with real-time Telegram message editing - /verbose command to show tool calls in streaming message - Sliding window display (last 8 tool lines, 15 text lines) to stay within 4096 limit - Newline separation between successive assistant message turns - Fork agent (haiku) for parallel queries when main agent is busy - /kill command to stop active agent - Fix duplicate messages from edit/sendMessage race condition - Fix verbose final message lost when edit fails silently - Fix verbose fallback duplicate on short text-only responses Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3139412 to
30b4243
Compare
… and /kill command From upstream PR moazbuilds#21 by 1872-svg (streaming + verbose) and PR moazbuilds#20 (fork agent). - Streaming output via editMessageText for real-time response display - /verbose command to show tool calls in Telegram - /fork command for parallel lightweight agent using Haiku - /kill command to terminate active agent - Auto-routing to fork when main agent is busy - Merged with additionalDirs (moazbuilds#13) and session corruption fix (moazbuilds#26) Co-Authored-By: 1872-svg <1872-svg@users.noreply.github.com>
- 重新組織為 Overview / Getting Started / Configuration / Features / Troubleshooting / Testing / Development - 加入完整 settings.json schema 範例(含所有欄位與註解) - 每個 feature 獨立章節:一句話說明 + 設定範例 + 行為說明 - 涵蓋所有已實作功能:Multi-Token Pool、OAuth、STT、Auto-Compact、Heartbeat、 Thread Hire/Fire、Session Metrics、Concurrent Processing、Skill System、 Graceful Shutdown、Structured Logging、Settings Hot-Reload - 移除重複內容,統一格式 - 新增 Troubleshooting 常見問題表 - 新增 Development 專案結構說明
TerrysPOV
left a comment
There was a problem hiding this comment.
Vision: PARTIAL — the streaming output feature is aligned and useful; the bundled fork/auto-routing re-introduces the silent implicit behavior that blocked PR #20.
Overlapping PRs: #82 (runner.ts + telegram.ts — session isolation; orthogonal concern but significant merge conflict risk on both files), #102 (runner.ts spawn env stripping — conflicts with new runClaudeStreaming spawn site)
Code review
Found 5 issues:
- Fork/kill/auto-routing re-introduced verbatim from closed PR #20 — the PR description says this depends on #20, which was closed with three specific requirements: (a) make routing opt-in via settings.json, (b) notify the user when routing to fork, (c) make FORK_MODEL configurable. None of these are addressed here.
Lines 519 to 555 in 30b4243
- Auto-routing is still always-on with no opt-in and no user notification — when isMainBusy() is true, the message silently routes to a Haiku fork with a different system prompt and no main-session context, with no indication to the user.
claudeclaw/src/commands/telegram.ts
Lines 763 to 775 in 30b4243
- execClaude rewrite silently drops merged features — the replacement removes agentic model routing (selectModel(), merged in PR #17), sessionTimeoutMs timeout handling, auto-compact on exit code 124, and thread session key routing. These were deliberately added across multiple merged PRs and are gone with no discussion.
Lines 377 to 475 in 30b4243
- activeProc overwritten by concurrent fork — /kill targets wrong process — runClaudeOnce (used by runFork) and runClaudeStreaming (main path) both write to the same module-level activeProc. A concurrent fork overwrites the main agent's process reference, making /kill kill the fork instead, and leaving the main agent untrackable.
Lines 161 to 165 in 30b4243
- Rate-limit fallback causes garbled streaming output — when the primary run hits a rate limit, runClaudeStreaming is retried with the same onChunk/onToolEvent callbacks. The Telegram stream message already has partial content from the first attempt; the fallback appends to the same accumulator, producing doubled/garbled output.
Lines 408 to 416 in 30b4243
The streaming output feature (makeStreamCallback, runClaudeStreaming, /verbose) is well-implemented and worth having — it doesn't overlap with #82 (which covers session isolation, an orthogonal concern).
A split would unblock it: a streaming-only PR that (a) doesn't include the fork/kill machinery, (b) preserves the agentic routing and timeout safeguards from master, rather than replacing execClaude wholesale, and (c) handles the rate-limit fallback callback reset.
Happy to review that version.
Summary
editMessageText. Sends a⏳placeholder on the first chunk, then progressively edits it as text arrives (throttled to 500ms). Final edit applies full HTML formatting.waitForStreamMsg()ensures the placeholdersendMessageresolves before the handler decides to edit-vs-send, eliminating duplicate messages when Claude responds faster than the API round-trip./verbosemode: Toggle per-chat display of tool calls. When on, the streaming message shows tool activity above the response text:/verboseis off by default — normal users see clean responses, power users can opt in.Implementation details
runner.ts: switched main execution from--output-format jsonto--output-format stream-json --verbose. AddedrunClaudeStreaming()which parses NDJSON line-by-line, delivers text deltas viaonChunk, and firesonToolEvent(line)for tool_use/tool_result events.telegram.ts:makeStreamCallback()builds a closure that manages the streaming message lifecycle. In verbose mode it maintains separatetoolLinesandtextAccbuffers and rebuilds the display on each flush.Test plan
/verbose→ send a prompt that uses tools — tool calls should appear in the message as they happen/verboseagain — should toggle off, responses go back to clean text